package studio.raptor.hub.in.service;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.apache.http.client.HttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import studio.raptor.hub.common.dto.EventMeta;
import studio.raptor.hub.common.model.Pair;
import studio.raptor.hub.in.model.EventNode;
import studio.raptor.hub.in.task.EventNodeTask;

/**
 * Created by liuyong8 on 2017/9/13.
 */
@Service
public class EventMsgService {
  private static final Logger log = LoggerFactory.getLogger(EventMsgService.class);

  @Autowired
  @Qualifier("hubInHttpClient")
  private HttpClient httpClient;
  @Autowired
  private StringRedisTemplate template;
  @Autowired
  private ApplicationContext context;
  @Autowired
  private Executor executor;
  private SetMultimap<Integer, EventNode> eventNodeMap;

  private static final String DATA_SOURCE_BEAN_NAME = "hubInDataSource";

  private static final String QUERY_EVENT_NODE = "SELECT event_kind_id,node_name,server_url,server_type FROM databus.event_node_server";

  @PostConstruct
  public void init() {
    //创建对象时，加载数据库配置
    eventNodeMap = HashMultimap.create();
    DataSource dataSource = context
        .getBean(DATA_SOURCE_BEAN_NAME, DataSource.class);

    Connection connection = null;
    Statement statement = null;
    try {
      connection = dataSource.getConnection();
      statement = connection.createStatement();
      ResultSet resultSet = statement.executeQuery(QUERY_EVENT_NODE);

      while (resultSet.next()) {
        EventNode eventNode = new EventNode();
        eventNode.setKindId(resultSet.getInt("event_kind_id"));
        eventNode.setNodeName(resultSet.getString("node_name"));
        eventNode.setServerUrl(resultSet.getString("server_url"));
        eventNode.setServerType(resultSet.getString("server_type"));
        eventNodeMap.put(eventNode.getKindId(),eventNode);
        log.info("kindId {},evetNode[{}]",eventNode.getKindId(),eventNode);
      }
    } catch (Exception e) {
      log.error("query event node data failed", e);
    }finally {
      try {
        if (statement != null) {
          statement.close();
        }

        if (connection != null) {
          connection.close();
        }

      } catch (SQLException e) {
        log.error("close connection error", e);
      }
    }

  }

  public String getEventMsg(Integer kindId, EventMeta eventMeta) throws Exception {

    //step1:获取对应kindId的节点信息,并塞入受理中心原始报文
    Set<EventNode> eventNodes = eventNodeMap.get(kindId);
    CompletionService<Pair<String, String>> eventMetaComp =
        new ExecutorCompletionService<Pair<String, String>>(executor);

    //step2:获取各个节点报文（线程池出发任务）
    for (EventNode eventNode : eventNodes) {
      String jsonNodeName = eventNode.getNodeName();
      String serverUrl = eventNode.getServerUrl();
      String serverType = eventNode.getServerType();
      eventMetaComp.submit(new EventNodeTask(kindId, jsonNodeName, serverUrl,
          serverType, eventMeta, httpClient));
    }

    //step3:所有节点报文获取完成后进行拼装
    StringBuilder sb = new StringBuilder();
    sb.append("{");
    String json = "";

    for (int i = 0; i < eventNodes.size(); i++) {
      Future<Pair<String, String>> future = eventMetaComp.take();
      if (future != null) {
        Pair<String, String> pair = future.get();
        String jsonNodeName = pair.getKey();
        String nodeValue = pair.getValue();

        if (nodeValue.trim().startsWith("{") || nodeValue.trim().startsWith("[")) {
          sb.append("\"" + jsonNodeName + "\"" + ":" + nodeValue + ",");
        } else {
          sb.append("\"" + jsonNodeName + "\"" + ":{" + nodeValue + "},");
        }
      }
    }
    json = sb.toString().substring(0, sb.toString().length() - 1) + "}";

    log.debug("json = {}",json);

    //step4:返回拼装结果
    return json;
  }

}
